#nullable enable

using System;
using System.Linq;
using System.Threading.Tasks;
using PHMEE.Entities.BaseInfo.Units;
using PHMEE.PHM.Algorithms.Diagnosis;
using Volo.Abp.Domain.Services;

namespace PHMEE.Managers.Diagnosis;

/// <summary>
/// 透平故障诊断
/// </summary>
public class TurbineFaultDiagnosisDomainService : DomainService, ITurbineFaultDiagnosisDomainService
{
    private readonly TurbineAlg _turbineAlg;

    public TurbineFaultDiagnosisDomainService(TurbineAlg turbineAlg)
    {
        _turbineAlg = turbineAlg;
    }

    /// <summary>
    /// 透平故障诊断
    /// </summary>
    /// <param name="pointPosition"></param>
    /// <param name="sampleRate"></param>
    /// <param name="unitWithEquips"></param>
    /// <param name="equipment"></param>
    /// <param name="data"></param>
    /// <exception cref="ArgumentNullException"></exception>
    /// <returns></returns>
    public async Task<string[]> FaultDiagnosisAsync(PointPosition pointPosition, float sampleRate,
        UnitWithEquipsDto unitWithEquips, Equipment equipment,
        float[] data)
    {
        // 设备参数和阈值初始化
        var equipmentParameters = new TurbineEquipmentParameters();
        var thresholds = new TurbineThresholds();
        
        if (equipment is not Turbocharger turbine)
        {
            throw new InvalidOperationException(nameof(Turbocharger));
        }

        // 提取透平参数
        ExtractTurbineParameters(turbine, equipmentParameters);

        // 提取阈值
        ExtractThresholds(unitWithEquips.Unit, thresholds);

        // TODO: 透平实时转速暂不知道如何取，暂时设置为最大转速
        float rpm = (float)turbine.MaxSpeed;

        // 调用透平故障诊断算法
        var response = await _turbineAlg.TurbineAsync(rpm, pointPosition, data, sampleRate,
            equipmentParameters, thresholds);

        return response.FaultCodes.ToArray();
    }

    private static void ExtractTurbineParameters(Turbocharger turbine,
        TurbineEquipmentParameters equipmentParameters)
    {
        equipmentParameters.Bp = turbine.TurbineBladeNumber;
        equipmentParameters.Power = (float)turbine.Power;
    }

    /// <summary>
    /// 从 Unit 提取阈值
    /// </summary>
    /// <param name="turbine"></param>
    /// <param name="thresholds"></param>
    private static void ExtractThresholds(Unit turbine, TurbineThresholds thresholds)
    {
        if (turbine is MainEngineUnit mainEngineUnit)
        {
            ExtractThresholdsForMainEngineUnit(mainEngineUnit, thresholds);
        }
        else
        {
            throw new InvalidOperationException(nameof(MainEngineUnit));
        }
        
    }
    
    /// <summary>
    /// 主机机组阈值提取
    /// </summary>
    /// <param name="unit"></param>
    /// <param name="thresholds"></param>
    private static void ExtractThresholdsForMainEngineUnit(MainEngineUnit unit, TurbineThresholds thresholds)
    {
        unit.DeserializeProperties();
        
        thresholds.TRms.AddRange(new []{ (float)unit.TrmsA, (float)unit.TrmsB, (float)unit.TrmsC });
        thresholds.TValue1X.AddRange(new []{ (float)unit.TValue1XA, (float)unit.TValue1XB });
        thresholds.TStructureLoose = (float)unit.TStructureLoose;
        thresholds.TResonanceFault = (float)unit.TResonanceFault;
        thresholds.TImpellerFault = (float)unit.TImpellerFault;
        thresholds.TImbalanceFault = (float)unit.TImbalanceFault;
        thresholds.TAxleWear.AddRange(new []{ (float)unit.TAxleWearA, (float)unit.TAxleWearB, (float)unit.TAxleWearC, (float)unit.TAxleWearD, (float)unit.TAxleWearE, (float)unit.TAxleWearF, (float)unit.TAxleWearG });
        thresholds.TRotationalStallOrSurge.AddRange(new []{ (float)unit.TRotationalStallOrSurgeA, (float)unit.TRotationalStallOrSurgeB });
    }
    
}